﻿/* 
   Copyright 2011 LUCA Studios LLC & John Evans

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;

namespace LUCAStudios.Silverlight.Controls
{
    using System.Windows;
    using System.Windows.Markup;
    using System.Windows.Controls;
    using System.Windows.Shapes;

    /// <summary>
    /// A window control that works in conjunction with the LUCALayoutPanel
    /// </summary>
    [ContentProperty("CurrentContent")]
    [TemplatePart(Name = CloseButton, Type=typeof(Button))]
    [TemplatePart(Name = MinimizeButton, Type = typeof(Button))]
    [TemplatePart(Name = MaximizeButton, Type = typeof(Button))]
    public class LUCAWindow : WindowBase
    {
        private bool _firstLoadOccurred;
        private Button _closeButton;
        private Button _minimizeButton;
        private Button _maximizeButton;

        private const string CloseButton = "btnCloseWindow";
        private const string MinimizeButton = "btnMinimizeWindow";
        private const string MaximizeButton = "btnMaximizeWindow";

        #region events

        public event EventHandler WindowClosing;
        public event EventHandler WindowMinimizing;
        public event EventHandler WindowMaximizing;

        #endregion

        /// <summary>
        /// Constructor
        /// </summary>
        public LUCAWindow()
        {
            DefaultStyleKey = typeof (LUCAWindow);
        }

        /// <summary>
        /// Indicates whether the window is in a minimized state.
        /// Currently not used but can be used by derived classes overriding OnWindowMinimizing()
        /// </summary>
        public bool IsMinimized { get; protected set; }
        /// <summary>
        /// Indicates whether the window is in a maximized state.
        /// Currently not used but can be used by derived classes overriding OnWindowMaximizing()
        /// </summary>
        public bool IsMaximized { get; protected set; }


        void InitEventHooks()
        {
            if (_closeButton == null)
                throw new LUCAControlException("Expected template references to be set.");

            _closeButton.Click += _closeButton_Click;
            _minimizeButton.Click += _minimizeButton_Click;
            _maximizeButton.Click += _maximizeButton_Click;
        }

        void _maximizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (WindowMaximizing != null) WindowMaximizing(this, new EventArgs());
            OnWindowMaximizing();
        }

        void _minimizeButton_Click(object sender, RoutedEventArgs e)
        {
            if (WindowMinimizing != null) WindowMinimizing(this, new EventArgs());
            OnWindowMinimizing();
        }

        void _closeButton_Click(object sender, RoutedEventArgs e)
        {
            if (WindowClosing != null) WindowClosing(this, new EventArgs());
            OnWindowClosing();
        }

        void DeInitEventHooks()
        {
            if (_closeButton == null) return;
            _closeButton.Click -= _closeButton_Click;
            _minimizeButton.Click -= _minimizeButton_Click;
            _maximizeButton.Click -= _maximizeButton_Click;
        }

        protected virtual void OnWindowClosing()
        {
            this.Remove();
        }

        protected virtual void OnWindowMinimizing()
        {
            
        }

        protected virtual void OnWindowMaximizing()
        {
            
        }

        #region overrides

        /// <summary>
        /// Called when the LUCA control is loaded
        /// </summary>
        protected override void OnLoaded()
        {
            base.OnLoaded();
            if (!_firstLoadOccurred) _firstLoadOccurred = true;
        }

        /// <summary>
        /// When overridden in a derived class, is invoked whenever application code or internal processes (such as a rebuilding layout pass) call <see cref="M:System.Windows.Controls.Control.ApplyTemplate"/>. In simplest terms, this means the method is called just before a UI element displays in an application. For more information, see Remarks.
        /// </summary>
        public override void OnApplyTemplate()
        {
            if (_firstLoadOccurred)
            {
                LayoutContext.WindowManipulator.UnregisterWindow(this);
                UnRegisterDockEvents();

                var cc = CurrentContent;
                var wi = WindowIcon;
                var t = Title;

                CurrentContent = null;
                WindowIcon = null;
                Title = null;
                
                base.OnApplyTemplate();

                DeInitEventHooks();

                _closeButton = GetTemplateChild(CloseButton) as Button;
                _minimizeButton = GetTemplateChild(MinimizeButton) as Button;
                _maximizeButton = GetTemplateChild(MaximizeButton) as Button;

                Title = t;
                CurrentContent = cc;
                WindowIcon = wi;

                DragHandle = null;
                InitializeControlReferences();
                LayoutContext.WindowManipulator.RegisterWindow(this);
                RegisterDockEvents();
            }else
            {
                base.OnApplyTemplate();
                _closeButton = GetTemplateChild(CloseButton) as Button;
                _minimizeButton = GetTemplateChild(MinimizeButton) as Button;
                _maximizeButton = GetTemplateChild(MaximizeButton) as Button;
                InitEventHooks();
            }
        }

        #endregion

        #region Dependency Properties

        /// <summary>
        /// Backing property for the CloseButtonVisibility property.  
        /// </summary>
        public static readonly DependencyProperty CloseButtonVisibilityProperty =
            DependencyProperty.Register("CloseButtonVisibility", typeof(Visibility), typeof(LUCAWindow), new PropertyMetadata(Visibility.Visible));

        /// <summary>
        /// Dependency property that determines whether the window close button is visible or not.  
        /// </summary>
        public Visibility CloseButtonVisibility
        {
            get { return (Visibility)GetValue(CloseButtonVisibilityProperty); }
            set { SetValue(CloseButtonVisibilityProperty, value); }
        }

        /// <summary>
        /// Backing property for the MinimizeButtonVisibility property.  
        /// </summary>
        public static readonly DependencyProperty MinimizeButtonVisibilityProperty =
            DependencyProperty.Register("MinimizeButtonVisibility", typeof (Visibility), typeof (LUCAWindow), new PropertyMetadata(Visibility.Collapsed));

        /// <summary>
        /// Dependency property that determines whether the window minimize button is visible or not.  
        /// This button is collapsed by default.  The LUCAWindow does not implement any behavior for this control natively.
        /// Use the OnWindowMinimizing() method in a derived class to hook in your own behavior. 
        /// </summary>
        public Visibility MinimizeButtonVisibility
        {
            get { return (Visibility) GetValue(MinimizeButtonVisibilityProperty); }
            set { SetValue(MinimizeButtonVisibilityProperty, value); }
        }


        /// <summary>
        /// Backing property for the MaximizeButtonVisibility property.  
        /// </summary>
        public static readonly DependencyProperty MaximizeButtonVisibilityProperty =
            DependencyProperty.Register("MaximizeButtonVisibility", typeof (Visibility), typeof (LUCAWindow), new PropertyMetadata(Visibility.Collapsed));
        
        /// <summary>
        /// Dependency property that determines whether the window minimize button is visible or not. 
        /// This button is collapsed by default.  The LUCAWindow does not implement any behavior for this control natively.
        /// Use the OnWindowMaximizing() method in a derived class to hook in your own behavior. 
        /// </summary>
        public Visibility MaximizeButtonVisibility
        {
            get { return (Visibility) GetValue(MaximizeButtonVisibilityProperty); }
            set { SetValue(MaximizeButtonVisibilityProperty, value); }
        }


        /// <summary>
        /// The title to be displayed in the LUCAWindowChrome
        /// Can be any type of Xaml Visual element, not just text.
        /// </summary>
        public object Title
        {
            get { return GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        /// <summary>
        /// Dependency property that holds Title property information
        /// </summary>
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(object), typeof(LUCAWindow),
                                                       new PropertyMetadata(null));

        /// <summary>
        /// Dependency property that holds the LUCAMenuStripContext information
        /// </summary>
        public static readonly DependencyProperty LUCAMenuStripContextProperty =
    DependencyProperty.Register("LUCAMenuStripContext", typeof(LUCAMenuStrip), typeof(LUCAWindow), new PropertyMetadata(default(LUCAMenuStrip)));

        /// <summary>
        /// Provids assignment of a LUCAMenuStrip to the window.  The window ui will adjust if this property is set.
        /// </summary>
        public LUCAMenuStrip LUCAMenuStripContext
        {
            get { return (LUCAMenuStrip)GetValue(LUCAMenuStripContextProperty); }
            set { SetValue(LUCAMenuStripContextProperty, value); }
        }

        #endregion

    }
}
